<?php
header("Content-type: text/html; charset=gbk");
include_once "Constant.php";
//Needed model file
include_once $_SERVER['DOCUMENT_ROOT']."/model/Stage.php";
include_once $_SERVER['DOCUMENT_ROOT']."/model/Undertake.php";
include_once $_SERVER['DOCUMENT_ROOT']."/model/Application.php";
//Needed dao file
include_once $_SERVER['DOCUMENT_ROOT']."/dao/StageDAO.php";
include_once $_SERVER['DOCUMENT_ROOT']."/dao/UndertakeDAO.php";
include_once $_SERVER['DOCUMENT_ROOT']."/dao/ApplicationDAO.php";

/**
 * map里存储的是stageId以及与stageId对应的AcceptStructure
 */
static $map =  array();

/**
 * Created by PhpStorm.
 * User: lwh
 * Date: 2017/7/27
 * Time: 9:33
 */
//接收post数据，并强制转换为关联数组
$data = $_POST['data'];
$para = json_decode($data,true);
$result = acceptTask($para);

function acceptTask($para){
    //输入参数
    $userId = $para["userid"];
    $taskId = $para["taskid"];
    $currentStage = $para["currentstage"];
    $startTime = $para["starttime"];
    $contractTime = $para["contracttime"];
    //构造接任务请求对象
    $requestBO = new RequestBO();
    $requestBO->setUserId($userId);
    $requestBO->setTaskId($taskId);
    $requestBO->setCurrentStage($currentStage);
    $requestBO->setStartTime($startTime);
    $requestBO->setContractTime($contractTime);

    //将请求插入application表当中
    $stageDAO = new StageDAO();
    $stage = $stageDAO->queryStageByTaskAndIndex($taskId, $currentStage);
    $stageId = $stage->getId();
    $insertResult = insertApplication($stageId,$userId);
    $isNeedWorker = isNeedMoreWorker($stageId);
    $acceptStructure = $GLOBALS['map']['$stageId'];
    //如果map里已有相应的structure
    if($acceptStructure != null){
        //如果未超时，将该requestBO添加到对应的list里
        if($acceptStructure->getFlag()){
            array_push($acceptStructure->getRequests(),$requestBO);
            $result = 1;
        }
        else{
            //超时分两种情况：第一种情况是该stage不再需要worker，那么直接返回-1；第二种情况则是需要额外的worker，那么新建structure覆盖并启动计时
            if($isNeedWorker){
                $result = createNewStructure($stageId,$requestBO);
            }
            else
                $result = -1;
        }
    }
    //为null表示第一次有人申请接受该任务，新建structure
    else{
        $result = createNewStructure($stageId,$requestBO);
    }

    return $result;
}

//创建新的结构体
function createNewStructure($stageId,$requestBO){
    $requests = array();
    array_push($requests,$requestBO);
    $waitingTime = Constant::$WAITING_TIME_WINDOW;
    $acceptStructure = new AcceptStructure($requests,$waitingTime);
    $GLOBALS['map']['$stageId'] = $acceptStructure;

    //Todo:计时并在MyTimerTask里面进行worker的选择
//    Timer timer = new Timer();
//    MyTimerTask myTask = new MyTimerTask(stageId,service);
//    timer.schedule(myTask, 30000);
    return 1;
}

//往application表中插入数据
function insertApplication($stageId,$userId){
    $applicationDAO = new ApplicationDAO();
    //设置要插入的数据，以数组的键值对形式
    $application = array();
    $application["userId"] = $userId;
    $application["stageId"] = $stageId;
    //获得插入结果
    $result = $applicationDAO->insert($application);
    return $result;
}

//判断是否还需要worker
function isNeedMoreWorker($stageId){
    $result = false;
    $undertakeDAO = new UndertakeDAO();
    //判断工人数量是否还有剩余名额
    $stageDAO = new StageDAO();
    $stage = $stageDAO->query($stageId);
    if($stage != null){
        $workerNum = $stage->getWorkerNum();
        $currentNum = count($undertakeDAO->queryByStage($stageId));
        if($currentNum < $workerNum)
            $result = true;
    }
    return $result;
}

class RequestBO{
    private $userId;
    private $taskId;
    private $currentStage;
    private $startTime;
    private $contractTime;

    /**
     * @return mixed
     */
    public function getUserId()
    {
        return $this->userId;
    }

    /**
     * @param mixed $userId
     */
    public function setUserId($userId)
    {
        $this->userId = $userId;
    }

    /**
     * @return mixed
     */
    public function getTaskId()
    {
        return $this->taskId;
    }

    /**
     * @param mixed $taskId
     */
    public function setTaskId($taskId)
    {
        $this->taskId = $taskId;
    }

    /**
     * @return mixed
     */
    public function getCurrentStage()
    {
        return $this->currentStage;
    }

    /**
     * @param mixed $currentStage
     */
    public function setCurrentStage($currentStage)
    {
        $this->currentStage = $currentStage;
    }

    /**
     * @return mixed
     */
    public function getStartTime()
    {
        return $this->startTime;
    }

    /**
     * @param mixed $startTime
     */
    public function setStartTime($startTime)
    {
        $this->startTime = $startTime;
    }

    /**
     * @return mixed
     */
    public function getContractTime()
    {
        return $this->contractTime;
    }

    /**
     * @param mixed $contractTime
     */
    public function setContractTime($contractTime)
    {
        $this->contractTime = $contractTime;
    }

}

class AcceptStructure{
    private $requests;
    private $timeWindow;
    private $flag;

    /**
     * AcceptStructure constructor.
     * @param $requests
     * @param $timeWindow
     * @param $flag
     */
    public function __construct($requests, $timeWindow)
    {
        $this->requests = $requests;
        $this->timeWindow = $timeWindow;
        $this->flag = true;
    }

    /**
     * @return mixed
     */
    public function getRequests()
    {
        return $this->requests;
    }

    /**
     * @param mixed $requests
     */
    public function setRequests($requests)
    {
        $this->requests = $requests;
    }

    /**
     * @return mixed
     */
    public function getTimeWindow()
    {
        return $this->timeWindow;
    }

    /**
     * @param mixed $timeWindow
     */
    public function setTimeWindow($timeWindow)
    {
        $this->timeWindow = $timeWindow;
    }

    /**
     * @return mixed
     */
    public function getFlag()
    {
        return $this->flag;
    }

    /**
     * @param mixed $flag
     */
    public function setFlag($flag)
    {
        $this->flag = $flag;
    }

}